<template>
  <a-select
    v-model:value="innerValue"
    @change="handleValueChange"
    :placeholder="placeholder"
    :showSearch="props.searchFlag"
    :allowClear="true"
    :filter-option="false"
    @search="handleSearch"
    @popupScroll="handlePopupScroll"
    :dropdown-match-select-width="false"
    :loading="loading"
    :mode="props.mode === 'multiple' ? 'multiple' : undefined"
    @focus="handleFocus"
    @blur="handleBlur"
    v-bind="$attrs"
  >
    <a-select-option v-for="item in options" :key="item.value" :value="item.value" :disabled="item.disabled">
      {{ item.label }}
    </a-select-option>

    <template #notFoundContent v-if="loading">
      <a-spin size="small" />
    </template>
  </a-select>
</template>

<script setup>
  import { onMounted, ref, watch, reactive, computed } from 'vue'
  import { debounce, castArray, isEmpty } from 'lodash-es'
  import { message } from 'ant-design-vue'

  import { strToArr } from '/@/utils/common'

  const props = defineProps({
    value: {
      type: [String, Number, Object, Array],
      default: null,
    },
    searchFlag: {
      type: Boolean,
      default: true,
    },
    mode: {
      type: String,
      default: 'single',
    },
    placeholder: {
      type: String,
      default: '请选择',
    },
    api: {
      type: Function,
      required: true,
    },
    // 初始化参数，为回显时使用
    initParams: {
      type: Object,
      default: () => ({}),
    },
    queryParams: {
      type: Object,
      default: () => ({}),
    },
    queryParamKey: {
      type: String,
      default: 'keyword',
    },
    responseAdapter: {
      type: Function,
      default: (res) => ({
        ...res,
        data: res.data,
        total: res.total,
      }),
    },
    // 新增属性，用于指定 value 字段名
    valueField: {
      type: String,
      default: 'id',
    },
    // 新增属性，用于指定 label 字段名
    labelField: {
      type: String,
      default: 'name',
    },
  })

  const emit = defineEmits(['update:value', 'change', 'focus', 'blur'])

  // 响应式状态
  const loading = ref(false)
  const searchKeyword = ref('')
  const hasMore = ref(true)
  const options = ref([])
  const innerValue = computed({
    get() {
      return props.mode === 'multiple' ? (Array.isArray(props.value) ? props.value : []) : props.value
    },
    set(newVal) {
      emit('update:value', newVal)
    },
  })

  // 分页配置
  const pagination = reactive({
    current: 1,
    pageSize: 10,
    total: 0,
  })
  const isFocused = ref(false)
  const handleFocus = () => {
    isFocused.value = true
    emit('focus')
  }
  const handleBlur = () => {
    isFocused.value = false
    emit('blur')
  }
  const initData = computed(() => {
    return searchKeyword.value || isFocused.value ? {} : props.initParams
  })
  // 核心请求方法
  const query = debounce(async () => {
    if (loading.value || !hasMore.value) return

    loading.value = true
    try {
      const params = {
        // ...initData.value,
        pageNo: pagination.current,
        pageSize: pagination.pageSize,
        ...props.queryParams,
      }
      // console.log('params==>', params)

      if (props.searchFlag && searchKeyword.value) {
        params[props.queryParamKey] = searchKeyword.value
      }
      // console.log('检索params', params)
      const rawRes = await props.api(params)
      const { data, total } = props.responseAdapter(rawRes)
      let labelFieldArr = strToArr(props.labelField)
      const resData = data.map((item) => {
        return {
          ...item,
          value: item[props.valueField],
          label: labelFieldArr
            .map((field) => item[field])
            .toString()
            .replace(/,/g, '-'),
        }
      })
      options.value = pagination.current === 1 ? resData : [...options.value, ...resData]
      pagination.total = total
      hasMore.value = options.value.length < total
      pagination.current++
      // console.log('options.value==>', options.value)
    } catch (error) {
      message.error(' 数据加载失败')
    } finally {
      loading.value = false
    }
  }, 300)

  // 回显时候的请求方法
  const initQuery = debounce(async () => {
    try {
      const params = {
        ...initData.value,
        pageNo: pagination.current,
        pageSize: pagination.pageSize,
        ...props.queryParams,
      }
      // console.log('params==>', params)

      if (props.searchFlag && searchKeyword.value) {
        params[props.queryParamKey] = searchKeyword.value
      }
      // console.log('检索params', params)
      const rawRes = await props.api(params)
      const { data, total } = props.responseAdapter(rawRes)
      let labelFieldArr = strToArr(props.labelField)
      const resData = data.map((item) => {
        return {
          ...item,
          value: item[props.valueField],
          label: labelFieldArr
            .map((field) => item[field])
            .toString()
            .replace(/,/g, '-'),
        }
      })
      const selectedValues = resData.filter((option) => !options.value.some((item) => item[props.valueField] === option[props.valueField]))
      options.value = [...options.value, ...selectedValues]
      // getSelectedOptions.value = [...options.value, ...resData]
      // console.log('options.value==>', options.value)
    } catch (error) {
      message.error(' 数据加载失败')
    }
  }, 300)

  // 事件处理
  const handleSearch = debounce((value) => {
    searchKeyword.value = value
    pagination.current = 1
    options.value = []
    hasMore.value = true
    query()
  }, 500)

  const handlePopupScroll = debounce((e) => {
    const { scrollTop, clientHeight, scrollHeight } = e.target
    if (scrollHeight - (scrollTop + clientHeight) < 10 && hasMore.value) {
      query()
    }
  }, 200)

  const handleValueChange = (value) => {
    if (value) {
      let val = castArray(value)
      getSelectedOptions.value = options.value.filter((option) => val.includes(option[props.valueField]))
    } else {
      getSelectedOptions.value = []
    }
    // 打印选择的值
    emit('change', value, getSelectedOptions.value)
  }

  // 获取选中项
  const getSelectedOptions = ref([])

  function initS() {
    // 重置分页参数并重新查询
    if (isEmpty(props.initParams) && isFocused.value) return
    // console.log('initParams', newParams)
    pagination.current = 1
    hasMore.value = true
    // query()
    initQuery()
  }

  // 初始化加载
  onMounted(() => {
    initS()
  })

  // 监听 queryParams 变化
  watch(
    [() => props.queryParams], //, () => isFocused.value
    (newParams, oldN) => {
      // 重置分页参数并重新查询

      pagination.current = 1
      options.value = []
      hasMore.value = true
      query()
    },
    { deep: true, immediate: true },
  )

  defineExpose({
    query,
    innerValue,
    options,
    getSelectedOptions,
  })
</script>
